﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BrokerBase.Lib;
using SaleLibrary.License;
using NHibernate;
using System.Data;
using NHibernate.Criterion;
using SaleLibrary.Score;
using SaleLibrary.Tools;
using BrokerBase.Lib.Person;
using BrokerBase.Lib.Core;
using BrokerBase.Lib.Client;
using BrokerBase.Lib.Tool;

namespace SaleLibrary.Sale
{
    public class Client:PKItem,IClient
    {
        /// <summary>
        /// 通过注册名判断一个注册用户是否存在
        /// 没有纳入事务管理，有潜在的逻辑问题。以后在修改
        /// </summary>
        /// <param name="name"></param>
        /// <param name="sess"></param>
        /// <returns></returns>
        public static bool ExistOfName(string name, ISession sess)
        {
            try
            {
                IDbCommand cmd = sess.Connection.CreateCommand();

                sess.Transaction.Enlist(cmd);

                string sql = "select count(*) from Sale_Client where Name=@UserName";

                cmd.CommandText = sql;
                IDbDataParameter p = cmd.CreateParameter();
                p.ParameterName = "@UserName";
                p.DbType = DbType.String;
                p.Size = 200;
                p.Value = name;
                cmd.Parameters.Add(p);
                int r = (int)cmd.ExecuteScalar();

                return r == 0 ? false : true;
            }
            catch (Exception er)
            {
                throw er;
            }
        }

        /// <summary>
        /// 通过注册名读取一个注册用户
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static Client LoadByName(string name,ISession sess)
        {
            IList<Client> cs = sess.CreateCriteria<Client>().Add(Restrictions.Eq("Name", name)).List<Client>();

            if (cs.Count > 0)
                return cs[0];
            else
                return null;
        }

        public static bool CheckClientVerify(RegistrantInfo regInfo,TerminalInfo terInfo,ISession sess)
        {
            string hql = "from ActiveCodeReg where Id=(select Max(r.Id) from ActiveCodeReg as r left join r.ActiveCode a left join a.Registrant as c where c.Name=:name)";

            IQuery q=sess.CreateQuery(hql);
            q.SetString("name",regInfo.UserName);

            ActiveCodeReg reg=q.UniqueResult<ActiveCodeReg>();

            if (reg != null && (reg.DISKSerialNo==terInfo.DISKSerialNo || reg.MACSerialNo==terInfo.MACSerialNo))
            {
                return true;
            }
            else
            {
                return false;
            }
                
        }

        #region INode<IClient> 成员

        /// <summary>
        /// 关联的所有注册码
        /// </summary>
        public virtual IList<ActiveCode> ActiveCodes { get; set; }

        /// <summary>
        /// 注册时间
        /// </summary>
        public virtual DateTime RegTime { get; set; }
        /// <summary>
        /// 真实姓名
        /// </summary>
        public virtual string RealName { get; set; }
        /// <summary>
        /// 生日
        /// </summary>
        public virtual DateTime? Birthday { get; set; }
        /// <summary>
        /// 性别
        /// </summary>
        public virtual SexType Sex { get; set; }
        /// <summary>
        /// 电子邮件
        /// </summary>
        public virtual string EMail { get; set; }
        /// <summary>
        /// 联系方式1
        /// </summary>
        public virtual string Contact1 { get; set; }
        /// <summary>
        /// 联系方式2
        /// </summary>
        public virtual string Contact2 { get; set; }
        /// <summary>
        /// 联系方式3
        /// </summary>
        public virtual string Contact3 { get; set; }
        /// <summary>
        /// 联系方式4
        /// </summary>
        public virtual string Contact4 { get; set; }
        /// <summary>
        /// 地址
        /// </summary>
        public virtual string Address { get; set; }
        /// <summary>
        /// 公式名称
        /// </summary>
        public virtual string CompanyName { get; set; }
        /// <summary>
        /// 密码，暂时没用
        /// </summary>
        public virtual string Password { get; set; }

        public virtual IClient Parent { get; set; }

        public virtual IList<IClient> Children{get;set;}

        public virtual int Level{get;set;}

        public virtual bool Leaf{get;set;}

        public virtual DateTime LastRegTime { get; set; }

        public virtual IScorePolicy Policy { get; set; }

        //public virtual IScoreRule DefaultScoreRule { get; set; }

        public virtual double TotalAmount { get; set; }

        public virtual double TotalScore { get; set; }
        /// <summary>
        /// 产品序列号(计算数字指纹，其它暂时没什么用)
        /// </summary>
        public virtual string LicenseCode { get; set; }
        /// <summary>
        /// 邀请码数量
        /// </summary>
        public virtual int InviteCodeQty { get; set; }

        public virtual DateTime CreateDate { get; set; }
        /// <summary>
        /// 判断是否是试用用户
        /// 有且有一次试用激活码的客户就是试用客户
        /// </summary>
        public virtual bool IsTrial
        {
            get
            {
                return ActiveCodes.Count == 1 && ActiveCodes[0].Edition == EditionType.Evaluation;
            }
        }

        public virtual IList<IScoreRecord> ScoreRecords { get; set; }


        public virtual DateTime GetMaxEndTime(ISession sess)
        {
            DateTime maxEndTime = sess.CreateSQLQuery("select Max(EndTime) from Sale_ActiveCode where RegistrantId=" + Id).UniqueResult<DateTime>();

            return maxEndTime;
        }

        public virtual IScoreRecord CreateOrUpdateScoreRecord(IScoreRecordType recType, ActiveCodeReg reg,IScoreRule rule, int level,string description,ISession sess)
        {
            string hql="from ScoreRecord where Client.Id="+this.Id +" and Provider.Id="+reg.ActiveCode.Registrant.Id;

            IScoreRecord sr = sess.CreateQuery(hql).UniqueResult<IScoreRecord>();

            if (sr == null)
                sr = new ScoreRecord();

            sr.ScoreTime = DateTimeUtil.ChinaStandardTime;
            sr.Client = this;
            sr.RecordType = recType;
            sr.Reg = reg;
            sr.Provider = reg.ActiveCode.Registrant;
            sr.IsTrial = reg.ActiveCode.Edition == EditionType.Evaluation ? true : false;
            sr.OppositeLevel = level;
            sr.Description = description;

            //只有大于规则最小金额才计算积分
            if(rule!=null && reg.ActiveCode.Amount>= rule.MinAmount)
                sr.Score = rule.Score * Math.Pow(rule.Scale, level-1);//计算积分

            return sr;
        }

        public virtual ActiveCode GetInviteCode(ISession sess)
        {

            ActiveCode ac=null;

            ITransaction tx = null;

            try
            {
                tx = sess.BeginTransaction();

                //IActiveCodeType codeType = sess.CreateCriteria<ActiveCodeType>().Add(Restrictions.Eq("TypeStyle", (int)ActiveCodeTypeStyle.Trial)).UniqueResult<IActiveCodeType>();

                DateTime dt=DateTimeUtil.ChinaStandardTime;

                ac = ActiveCode.CreateActiveCode(EditionType.Evaluation, 1, 30);

                ac.Presenter = this;
                ac.SendTime = dt;

                ActiveCodeSend send = ac.CreateSend();
                send.Sender = this;
                send.SendTime = dt;
                ac.Sends.Add(send);

                sess.SaveOrUpdate(ac);

                InviteCodeQty--;//可用邀请码减一

                sess.SaveOrUpdate(this);

                tx.Commit();
            }
            catch (Exception er)
            {
                if (tx.IsActive)
                    tx.Rollback();

                throw er;
            }

            return ac;

        }

        public virtual string FullPath { get; set; }

        public virtual void UpdateScore(double score, ISession sess)
        {
            string sql = string.Format("update Sale_Client set TotalScore=TotalScore+{0} where id={1}", score, Id);
            IDbCommand cmd=sess.Connection.CreateCommand();

            sess.Transaction.Enlist(cmd);

            cmd.CommandText=sql;
            cmd.ExecuteNonQuery();
        }

        #endregion
    }
}
